package com.itheima.ssm.controller;

import com.itheima.ssm.domain.SysLog;
import com.itheima.ssm.service.ISysLogService;
import com.itheima.ssm.utils.DateUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Date;

@Component
@Aspect
public class LogAop {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private ISysLogService sysLogService;

    private Date visitTime;//访问的开始时间
    private Class clazz;//访问的类
    private Method method;//访问的方法


    //前置通知 主要是获取开始时间，执行的类是哪一个，执行的是哪一个方法
    @Before("execution(* com.itheima.ssm.controller.*.*(..))")
    public void doBefore(JoinPoint jp) throws NoSuchMethodException {
        visitTime= new Date();//当前时间是开始访问的时间
        clazz=jp.getTarget().getClass();//具体要访问的类
        String methodName=jp.getSignature().getName();//获取到方法的名字

        Object[] args = jp.getArgs();//获取访问的方法的参数

        //获取具体执行的方法的Method对象
        if (args==null||args.length==0){
            method=clazz.getMethod(methodName);//只能获取无参数的方法
        }else {
            Class[] classArgs=new Class[args.length];
            for(int i=0;i<args.length;i++){
                classArgs[i]=args[i].getClass();
            }
            clazz.getMethod(methodName,classArgs);
        }

    }


    //后置通知
    @After("execution(* com.itheima.ssm.controller.*.*(..))")
    public void doAfter(JoinPoint jp) throws Exception {
        long time=new Date().getTime()-visitTime.getTime();//获取访问时长

        String url="";
        //获取URL
        if (clazz!=null&&method!=null  && clazz!= LogAop.class){

            //1.获取大类注解值@RequestMapping("/orders")
            RequestMapping clazzAnnotation =(RequestMapping)clazz.getAnnotation(RequestMapping.class);
            if (clazzAnnotation!=null){
                String classValue = clazzAnnotation.value()[0];

                //获取方法注解中的value
                RequestMapping methodAnnotation =(RequestMapping)method.getAnnotation(RequestMapping.class);
                if (methodAnnotation!=null){
                   String methodValue= methodAnnotation.value()[0];

                   url=classValue+methodValue;

                    //获取访问的ip地址
                    String ip=request.getRemoteAddr();//获取当前访问的ip地址

                    //获取当前操作的用户
                    SecurityContext context= SecurityContextHolder.getContext();//从上下文中获取当前登录的用户
                    //也可以通过session中spring-security的保存信息中获取
                    User user = (User) context.getAuthentication().getPrincipal();
                    String username = user.getUsername();
                    System.out.println(username);

                    //将日志相关信息封装到SysLog对象中
                    SysLog sysLog=new SysLog();
                    sysLog.setExecutionTime(time);
                    sysLog.setIp(ip);
                    sysLog.setUrl(url);
                    sysLog.setUsername(username);
                    sysLog.setVisitTime(visitTime);
                    sysLog.setMethod("[类名]"+clazz.getName()+"[方法名]"+method.getName());

                    //调用Service完成日志记录操作
                    sysLogService.save(sysLog);
                }

            }


        }

    }
}





















